home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / hexcalc-1.11 / hexcalc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-23  |  24.2 KB  |  1,005 lines

  1.  
  2. /* hexcalc - A simple hex calculator for X
  3.  *
  4.  * Copyright 1989 Thomas J. Jarmolowski
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of the author not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  The author makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Tom Jarmolowski
  24.  *        jarmolowski%esdsdf.decnet@crd.ge.com
  25.  *
  26.  *        GESD
  27.  *        Borton Landing Road
  28.  *        Moorestown NJ
  29.  *        MS 108-204
  30.  *    
  31.  *        (609) 722-4298
  32.  */
  33.  
  34.  
  35. #ifndef lint
  36. static char *sccsid = "@(#)hexcalc.c    1.11  11/21/89";
  37. #endif    
  38.  
  39. #include    <stdio.h>
  40. #include    <ctype.h>
  41. #include    <X11/IntrinsicP.h>
  42. #include    <X11/StringDefs.h>
  43. #include    <X11/Xaw/Form.h>
  44. #include    <X11/Xaw/Label.h>
  45. #include    <X11/Xaw/Command.h>
  46. #include    <X11/Xaw/Paned.h>
  47. #include    <X11/Xaw/Grip.h>
  48.  
  49. /********************************/
  50. /*    Private Types        */
  51. /********************************/
  52. typedef    struct    {
  53.     char        *name;
  54.     char        *type;
  55.     Widget        w;
  56.     Widget        *wPtr;
  57.     XtCallbackRec    callback[2];
  58. } ButtonList;
  59.  
  60. /********************************/
  61. /*    Private Macros        */
  62. /********************************/
  63. #define    resetArgs()        argCount = 0
  64.  
  65. #define    setArg(what, value)    XtSetArg(args[argCount], what, value);\
  66.                 argCount++
  67.  
  68. #define    createManagedWidget(name, class, parent)\
  69.             XtCreateManagedWidget(name, class, parent, args, argCount);
  70.  
  71.  
  72. #define    Beep()            XBell(XtDisplay(topLevel), 50)
  73.  
  74. #define    streq(a, b)        (strcmp(a, b) == 0)
  75.  
  76. #define    PRIVATE    static
  77. #define    PUBLIC
  78.  
  79. #define    PushArg(n)        argStack[argStackP++] = n
  80. #define    PopArg()        argStack[--argStackP]
  81.  
  82. #define    initArgs()        argStackP = 0;
  83. #define    emptyArgs()        (argStackP == 0);
  84.  
  85. #define    PushOp(n)        opStack[opStackP++] = n
  86. #define    PopOp()            opStack[--opStackP]
  87. #define    initOps()        opStackP = 0;
  88. #define    emptyOps()        (opStackP == 0);
  89. #define    TopOp()            opStack[opStackP-1]
  90.  
  91. /********************************/
  92. /*    Private Routines    */
  93. /********************************/
  94. static    void    Delete();
  95. static    void    FlipButton(/* w */);
  96. static    void    DoKey(/* w, event, params, numParams */);
  97. static    void    Neg();
  98. static    void    Store();
  99. static    void    Recall();
  100. static    void    ClearM();
  101. static    int    Left(/* token */);
  102. static    int    Right(/* token */);
  103. static    void    Not();
  104. static    void    Op(/* w, data */);
  105. static    void    UpdateDisplay();
  106. static    void    Radix(/* w, data */);
  107. static    void    SetRadixButtons();
  108. static    void    Off();
  109. static    void    SetSize(/* w, data */);
  110. static    void    SetSizeButtons();
  111. static    void    SetSign(/* w, data */);
  112. static    void    SetSignButtons();
  113. static    void    Digit(/* w, data */);
  114. static    void    Clear();
  115. static    void    AllClear();
  116. static    Widget    MakeButtons(/* parent */);
  117. static    Widget    MakeDisplay(/* parent */);
  118. static    void    MakeHexcalc(/* parent */);
  119.  
  120. /********************************/
  121. /*    Private data        */
  122. /********************************/
  123. static    int        ac = 0;
  124. static    int        radix    = 10;
  125. static    Widget        display = NULL;
  126. static    Widget        topLevel = NULL;
  127. static    int        memory = 0;
  128. static    Boolean        isSigned = True;
  129. static    int        bitsWide = 32;
  130. static    Boolean        newNumber = True;
  131. static    Boolean        acPushed = False;
  132. static    int        argStackP = 0;
  133. static    int        argStack[100];
  134. static    int        opStackP = 0;
  135. static    int        opStack[100];
  136. static    XtTranslations    translations;
  137.  
  138. static    Widget    hexW;
  139. static    Widget    binW;
  140. static    Widget    octW;
  141. static    Widget    decW;
  142. static    Widget    shortW;
  143. static    Widget    longW;
  144. static    Widget    signW;
  145. static    Widget    usignW;
  146.  
  147. static    ButtonList buttonList[] = {
  148.  
  149.     {"dec",        "baseKey",    NULL,    &decW,    {Radix,    (caddr_t) 10}},
  150.     {"hex",        "baseKey",    NULL,    &hexW,    {Radix,    (caddr_t) 16}},
  151.     {"oct",        "baseKey",    NULL,    &octW,    {Radix,    (caddr_t) 8}},
  152.     {"bin",        "baseKey",    NULL,    &binW,    {Radix,    (caddr_t) 2}},
  153.     {"off",        "controlKey",    NULL,    NULL,    {Off,    NULL}},
  154.  
  155.     {"16",        "sizeKey",    NULL,    &shortW,{SetSize,  (caddr_t) 16}},
  156.     {"32",        "sizeKey",    NULL,    &longW,    {SetSize,  (caddr_t) 32}},
  157.     {"sgn",        "signKey",    NULL,    &signW,    {SetSign,  (caddr_t) True}},
  158.     {"unsgn",    "signKey",    NULL,    &usignW,{SetSign,  (caddr_t) False}},
  159.     {"C",        "controlKey",    NULL,    NULL,    {AllClear, NULL}},
  160.  
  161.     {"Sto",        "memKey",    NULL,    NULL,    {Store, NULL}},
  162.     {"Rcl",        "memKey",    NULL,    NULL,    {Recall, NULL}},
  163.     {"Clr",        "memKey",    NULL,    NULL,    {ClearM, NULL}},
  164.     {"(",        "evalKey",    NULL,    NULL,    {Op,    (caddr_t) '('}},
  165.     {")",        "evalKey",    NULL,    NULL,    {Op,    (caddr_t) ')'}},
  166.  
  167.     {"<<",        "shiftKey",    NULL,    NULL,    {Op,    (caddr_t) '<'}},
  168.     {"d",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 13}},
  169.     {"e",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 14}},
  170.     {"f",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 15}},
  171.     {">>",        "shiftKey",    NULL,    NULL,    {Op,    (caddr_t) '>'}},
  172.  
  173.     {"~",        "bitKey",    NULL,    NULL,    {Not, NULL}},
  174.     {"a",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 10}},
  175.     {"b",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 11}},
  176.     {"c",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 12}},
  177.     {"/",        "arithKey",    NULL,    NULL,    {Op,    (caddr_t) '/'}},
  178.     
  179.     {"|",        "bitKey",    NULL,    NULL,    {Op,    (caddr_t) '|'}},
  180.     {"7",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 7}},
  181.     {"8",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 8}},
  182.     {"9",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 9}},
  183.     {"*",        "arithKey",    NULL,    NULL,    {Op,    (caddr_t) '*'}},
  184.  
  185.     {"&",        "bitKey",    NULL,    NULL,    {Op,    (caddr_t) '&'}},
  186.     {"4",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 4}},
  187.     {"5",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 5}},
  188.     {"6",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 6}},
  189.     {"-",        "arithKey",    NULL,    NULL,    {Op,    (caddr_t) '-'}},
  190.  
  191.     {"^",        "bitKey",    NULL,    NULL,    {Op,    (caddr_t) '^'}},
  192.     {"1",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 1}},
  193.     {"2",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 2}},
  194.     {"3",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 3}},
  195.     {"+",        "arithKey",    NULL,    NULL,    {Op,    (caddr_t) '+'}},
  196.  
  197.     {"CE/E",    "controlKey",    NULL,    NULL,    {Clear, NULL}},
  198.     {"0",        "digitKey",    NULL,    NULL,    {Digit,    (caddr_t) 0}},
  199.     {"",        "",        NULL,    NULL,    {NULL, NULL}},
  200.     {"+/-",        "",        NULL,    NULL,    {Neg,    (caddr_t) 0}},
  201.     {"=",        "evalKey",    NULL,    NULL,    {Op,    (caddr_t) '='}},
  202.         
  203. };
  204.  
  205. static    XtActionsRec    actions[] = {
  206.     {"DoKey",     DoKey},
  207.     {"Delete",     Delete},
  208. };
  209.  
  210. static    String        defaultTranslations    =
  211.     ":<Key>(:        DoKey(\"(\")\n\
  212.      :<Key>&:        DoKey(&)\n\
  213.      :<Key>^:        DoKey(^)\n\
  214.      :<Key>):        DoKey(\")\")\n\
  215.      Ctrl<Key>c:        DoKey(off)\n\
  216.      :<Key>H:        DoKey(hex)\n\
  217.      :<Key>O:        DoKey(oct)\n\
  218.      :<Key>D:        DoKey(dec)\n\
  219.      :<Key>B:        DoKey(bin)\n\
  220.      :<Key>R:        DoKey(Rcl)\n\
  221.      :<Key>S:        DoKey(Sto)\n\
  222.      :<Key>s:        DoKey(16)\n\
  223.      :<Key>l:        DoKey(32)\n\
  224.      :<Key>+:        DoKey(+)\n\
  225.      :<Key>-:        DoKey(-)\n\
  226.      :<Key>*:        DoKey(*)\n\
  227.      :<Key>/:        DoKey(/)\n\
  228.      :<Key>%:        DoKey(%)\n\
  229.      :<Key>>:        DoKey(>>)\n\
  230.      :<Key><:        DoKey(<<)\n\
  231.      :<Key>0:        DoKey(0)\n\
  232.      :<Key>1:        DoKey(1)\n\
  233.      :<Key>2:        DoKey(2)\n\
  234.      :<Key>3:        DoKey(3)\n\
  235.      :<Key>4:        DoKey(4)\n\
  236.      :<Key>5:        DoKey(5)\n\
  237.      :<Key>6:        DoKey(6)\n\
  238.      :<Key>7:        DoKey(7)\n\
  239.      :<Key>8:        DoKey(8)\n\
  240.      :<Key>9:        DoKey(9)\n\
  241.      :<Key>a:        DoKey(a)\n\
  242.      :<Key>b:        DoKey(b)\n\
  243.      :<Key>c:        DoKey(c)\n\
  244.      :<Key>d:        DoKey(d)\n\
  245.      :<Key>e:        DoKey(e)\n\
  246.      :<Key>f:        DoKey(f)\n\
  247.      Ctrl<Key>h:        Delete()\n\
  248.      <Key>Delete:        Delete()\n\
  249.      :<Key>=:        DoKey(=)\n\
  250.      :<Key>Return:        DoKey(=)"
  251. ;
  252.  
  253.  
  254. /****************************************************************/
  255. /*                                */
  256. /*   ROUTINE NAME:    Delete                    */
  257. /*                                */
  258. /*   PURPOSE:    Delete a digit                    */
  259. /*                                */
  260. /****************************************************************/
  261. PRIVATE    void    Delete()
  262. {
  263.     if (ac) {
  264.         ac = ((unsigned) ac) / radix;
  265.         UpdateDisplay();
  266.     }
  267.     
  268. }
  269.  
  270.  
  271. /****************************************************************/
  272. /*                                */
  273. /*   ROUTINE NAME:    FlipButton                */
  274. /*                                */
  275. /*   PURPOSE:    Reverse video a button.                */
  276. /*                                */
  277. /****************************************************************/
  278. PRIVATE    void    FlipButton(w)
  279. Widget        w;
  280. {
  281.     int        argCount;
  282.     Arg        args[10];
  283.     Pixel        foreground;
  284.     Pixel        background;
  285.     
  286.     resetArgs();
  287.     setArg(XtNforeground, &foreground);
  288.     setArg(XtNbackground, &background);
  289.     XtGetValues(w, args, argCount);
  290.  
  291.     resetArgs();
  292.     setArg(XtNforeground, background);
  293.     setArg(XtNbackground, foreground);
  294.     XtSetValues(w, args, argCount);
  295. }
  296.  
  297.  
  298. /****************************************************************/
  299. /*                                */
  300. /*   ROUTINE NAME:    DoKey                    */
  301. /*                                */
  302. /*   PURPOSE:    Execute a key by name                */
  303. /*                                */
  304. /****************************************************************/
  305. /* ARGSUSED */
  306. PRIVATE    void    DoKey(w, event, params, numParams)
  307. Widget        w;
  308. XEvent        *event;
  309. String        *params;
  310. int        *numParams;
  311. {
  312.  
  313.     int        i;
  314.     Boolean        match;
  315.     int        args = *numParams;
  316.     
  317.     while (args--) {
  318.         match = False;
  319.         for (i = 0; i < XtNumber(buttonList); i++) {
  320.             if (streq(*params, buttonList[i].name)) {
  321.                 FlipButton(buttonList[i].w);
  322.                 (*buttonList[i].callback[0].callback)
  323.                         (buttonList[i].w, buttonList[i].callback[0].closure, NULL);
  324.                 FlipButton(buttonList[i].w);
  325.                 match = True;
  326.                 break;
  327.             }
  328.         }
  329.  
  330.         if (!match) {
  331.             (void) fprintf(stderr, "No key named \"%s\".\n", *params);
  332.         }
  333.         params++;
  334.     }
  335. }
  336.  
  337.  
  338. /****************************************************************/
  339. /*                                */
  340. /*   ROUTINE NAME:    Neg                    */
  341. /*                                */
  342. /*   PURPOSE:    Change sign of the ac                */
  343. /*                                */
  344. /****************************************************************/
  345. PRIVATE    void    Neg()
  346. {
  347.     ac = -ac;
  348.     newNumber = True;
  349.     UpdateDisplay();
  350. }
  351.  
  352.  
  353. /****************************************************************/
  354. /*                                */
  355. /*   ROUTINE NAME:    store                    */
  356. /*                                */
  357. /*   PURPOSE:    Save the current AC                */
  358. /*                                */
  359. /****************************************************************/
  360. PRIVATE    void    Store()
  361. {
  362.     newNumber = True;
  363.     memory = ac;
  364. }
  365.  
  366.  
  367. /****************************************************************/
  368. /*                                */
  369. /*   ROUTINE NAME:    Recall                    */
  370. /*                                */
  371. /*   PURPOSE:    Load AC from memory.                */
  372. /*                                */
  373. /****************************************************************/
  374. PRIVATE    void    Recall()
  375. {
  376.     ac = memory;
  377.     newNumber = True;
  378.     UpdateDisplay();
  379. }
  380.  
  381. /****************************************************************/
  382. /*                                */
  383. /*   ROUTINE NAME:    ClearM                    */
  384. /*                                */
  385. /*   PURPOSE:    Clear memory.                     */
  386. /*                                */
  387. /****************************************************************/
  388. PRIVATE    void    ClearM()
  389. {
  390.     memory = 0;
  391. }
  392.  
  393. /****************************************************************/
  394. /*                                */
  395. /*   ROUTINE NAME:    Left                    */
  396. /*                                */
  397. /*   PURPOSE:    Determine the precedence of this operator     */
  398. /* on the left.                            */
  399. /*                                */
  400. /****************************************************************/
  401. PRIVATE    int    Left(token)
  402. char        token;
  403. {
  404.     switch (token) {
  405.     case '*'  : return (16);
  406.     case '/'  : return (16);
  407.     case '%'  : return (16);
  408.     case '+'  : return (8);
  409.     case '-'  : return (8);
  410.     case '<'  : return (4);
  411.     case '>'  : return (4);
  412.     case '&'  : return (2);
  413.     case '^'  : return (2);
  414.     case '|'  : return (2);
  415.     case '('  : return (0);
  416.     case ')'  : return (18);
  417.     case '$'  : return (-1);
  418.     case '='  : return (18);
  419.     default      :
  420.         (void) fprintf(stderr, "I don't know what to do with %c\n", token);
  421.         exit(1);
  422.     }
  423. /* NOTREACHED */
  424. }
  425.  
  426.  
  427.  
  428. /****************************************************************/
  429. /*                                */
  430. /*   ROUTINE NAME:    Right                    */
  431. /*                                */
  432. /*   PURPOSE:    Determine the precedence of this operator     */
  433. /* on the right.                        */
  434. /*                                */
  435. /****************************************************************/
  436. PRIVATE    int    Right(token)
  437. char        token;
  438. {
  439.     switch (token) {
  440.     case '*'  : return (15);
  441.     case '/'  : return (15);
  442.     case '%'  : return (15);
  443.     case '+'  : return (7);
  444.     case '-'  : return (7);
  445.     case '<'  : return (3);
  446.     case '>'  : return (3);
  447.     case '&'  : return (1);
  448.     case '^'  : return (1);
  449.     case '|'  : return (1);
  450.     case '('  : return (17);
  451.     case ')'  : return (-1);
  452.     case '='  : return (-1);
  453.     default      :
  454.         (void) fprintf(stderr, "I don't know what to do with %c\n", token);
  455.         exit(1);
  456.     }
  457. /* NOTREACHED */
  458. }
  459.  
  460.  
  461.  
  462. /****************************************************************/
  463. /*                                */
  464. /*   ROUTINE NAME: Not                        */
  465. /*                                */
  466. /*   PURPOSE: Bitwise invertions of the accumulator        */
  467. /*                                */
  468. /****************************************************************/
  469. PRIVATE    void    Not()
  470. {
  471.     ac = ~ac;
  472.     newNumber = True;
  473.     UpdateDisplay();
  474. }
  475.  
  476.  
  477. /****************************************************************/
  478. /*                                */
  479. /*   ROUTINE NAME: Op                        */
  480. /*                                */
  481. /*   PURPOSE: Process an operator                */
  482. /*                                */
  483. /****************************************************************/
  484. /* ARGSUSED */
  485. PRIVATE    void    Op(w, data)
  486. Widget        w;
  487. caddr_t        data;
  488. {
  489.     char    op = (char) data;
  490.     int    temp;
  491.     char    topOp;
  492.         
  493.     /************************************************/
  494.     /* If accumulator has a number, stack it.    */
  495.     /************************************************/    
  496.     if (!acPushed) {
  497.         newNumber = True;
  498.         acPushed = True;
  499.         PushArg(ac);
  500.     }
  501.  
  502.     /************************************************/
  503.     /* Process operators according to their        */
  504.     /* precedence.                    */
  505.     /************************************************/
  506.     while (Left(TopOp()) > Right(op)) {
  507.         topOp = PopOp();
  508.         if ((topOp == '(') && op == ')') break;
  509.  
  510.         switch(topOp) {
  511.         case '+' :
  512.             ac = PopArg()  + PopArg();
  513.             break;
  514.         case '-' :
  515.             temp = PopArg();
  516.             ac = PopArg() - temp;
  517.             break;
  518.         case '*' :
  519.             ac = PopArg()  * PopArg();
  520.             break;
  521.         case '/' :
  522.             temp = PopArg();
  523.             ac = PopArg()/temp;
  524.             break;
  525.         case '%' :
  526.             temp = PopArg();
  527.             ac = PopArg() % temp;
  528.             break;
  529.             
  530.         case '|' :
  531.             ac = PopArg() | PopArg();
  532.             break;
  533.  
  534.         case '&' :
  535.             ac = PopArg() & PopArg();
  536.             break;
  537.  
  538.         case '^' :
  539.             ac = PopArg() ^ PopArg();
  540.             break;
  541.  
  542.         case '<' :
  543.             temp = PopArg();
  544.             ac = PopArg() << temp;
  545.             break;
  546.             
  547.         case '>' :
  548.             temp = PopArg();
  549.             ac = PopArg() >> temp;
  550.             break;
  551.             
  552.         case '(' :
  553.         case '=' :
  554.             ac = PopArg();
  555.             break;
  556.         }
  557.  
  558.         UpdateDisplay();
  559.         PushArg(ac);
  560.     }
  561.  
  562.     if ((op != ')') && (op != '=')) {
  563.         PushOp(op);
  564.     }
  565. }
  566.  
  567.  
  568. /****************************************************************/
  569. /*                                */
  570. /*   ROUTINE NAME: UpdateDisplay                */
  571. /*                                */
  572. /*   PURPOSE:    Display the accumulator                */
  573. /*                                */
  574. /****************************************************************/
  575. PRIVATE    void    UpdateDisplay()
  576. {
  577.     char        text[50];
  578.     int        argCount;
  579.     Arg        args[10];
  580.     unsigned    i;
  581.     unsigned    ac2    = (bitsWide == 32) ? ac : (ac & 0xffff);
  582.     short        acShort = ac;
  583.     
  584.     switch (radix) {
  585.     case 2:
  586.         text[0] = '\0';
  587.         for (i = (bitsWide == 32) ? 0x80000000 : 0x8000; i; i >>= 1) {
  588.             if (i & ac2) {
  589.                 (void) strcat(text, "1");
  590.             } else {
  591.                 (void) strcat(text, "0");
  592.             }
  593.         }
  594.         break;
  595.     case 8:
  596.         (void) sprintf(text, (bitsWide == 32) ? "%011o" : "%06o", ac2);
  597.         break;
  598.     case 10:
  599.         (void) sprintf(text, isSigned ? "%d" : "%u", (bitsWide == 32) ? ac : (isSigned ? acShort : ac2));
  600.         break;
  601.     case 16:
  602.         (void) sprintf(text, (bitsWide == 32) ? "%08x" : "%04x", ac2);
  603.         break;
  604.     }
  605.  
  606.  
  607.     resetArgs();
  608.     setArg(XtNlabel, text);
  609.     XtSetValues(display, args, argCount);
  610. }
  611.  
  612.  
  613. /****************************************************************/
  614. /*                                */
  615. /*   ROUTINE NAME: Radix                    */
  616. /*                                */
  617. /*   PURPOSE:    Change the I/O radix                */
  618. /*                                */
  619. /****************************************************************/
  620. /* ARGSUSED */
  621. PRIVATE    void    Radix(w, data)
  622. Widget        w;
  623. caddr_t        data;
  624. {
  625.     int    newRadix = (int) data;
  626.  
  627.     if (radix != newRadix) {
  628.         newNumber = True;
  629.         radix = newRadix;
  630.         UpdateDisplay();
  631.         SetRadixButtons();
  632.     }
  633. }
  634.  
  635. /****************************************************************/
  636. /*                                */
  637. /*   ROUTINE NAME: SetRadixButtons                */
  638. /*                                */
  639. /*   PURPOSE:    Make the current radix insensitive        */
  640. /*                                */
  641. /****************************************************************/
  642. PRIVATE    void    SetRadixButtons()
  643. {
  644.  
  645.     XtSetSensitive(hexW, True);
  646.     XtSetSensitive(decW, True);
  647.     XtSetSensitive(octW, True);
  648.     XtSetSensitive(binW, True);
  649.  
  650.     switch(radix) {
  651.     case 16 :
  652.         XtSetSensitive(hexW, False);
  653.         break;
  654.     case 10 :
  655.         XtSetSensitive(decW, False);
  656.         break;
  657.     case 8  :
  658.         XtSetSensitive(octW, False);
  659.         break;
  660.     case 2  :
  661.         XtSetSensitive(binW, False);
  662.         break;
  663.     }
  664. }
  665.  
  666.  
  667. /****************************************************************/
  668. /*                                */
  669. /*   ROUTINE NAME:    Off                    */
  670. /*                                */
  671. /*   PURPOSE: Exit.                        */
  672. /*                                */
  673. /****************************************************************/
  674. PRIVATE    void    Off()
  675. {
  676.     exit(0);
  677. }
  678.  
  679.  
  680. /****************************************************************/
  681. /*                                */
  682. /*   ROUTINE NAME:    SetSize                    */
  683. /*                                */
  684. /*   PURPOSE:    Set 16 or 32 bit mode                */
  685. /*                                */
  686. /****************************************************************/
  687. /* ARGSUSED */
  688. PRIVATE    void    SetSize(w, data)
  689. Widget        w;
  690. caddr_t        data;
  691. {
  692.     int    bits = (int) data;
  693.  
  694.     if (bits != bitsWide) {
  695.         bitsWide = bits;
  696.         UpdateDisplay();
  697.         SetSizeButtons();
  698.     }
  699. }
  700.  
  701.  
  702. /****************************************************************/
  703. /*                                */
  704. /*   ROUTINE NAME:    SetSizeButtons                */
  705. /*                                */
  706. /*   PURPOSE:    Enable/disable size buttons            */
  707. /*                                */
  708. /****************************************************************/
  709. PRIVATE    void    SetSizeButtons()
  710. {
  711.     if (bitsWide == 16) {
  712.         XtSetSensitive(longW, True);
  713.         XtSetSensitive(shortW, False);
  714.     } else {
  715.         XtSetSensitive(longW, False);
  716.         XtSetSensitive(shortW, True);
  717.     }
  718. }
  719.  
  720. /****************************************************************/
  721. /*                                */
  722. /*   ROUTINE NAME:    SetSign                    */
  723. /*                                */
  724. /*   PURPOSE:    Set signed or unsigned mode            */
  725. /*                                */
  726. /****************************************************************/
  727. /* ARGSUSED */
  728. PRIVATE    void    SetSign(w, data)
  729. Widget        w;
  730. caddr_t        data;
  731. {
  732.     Boolean newSign = (Boolean) data;
  733.     if (newSign != isSigned) {
  734.         isSigned = newSign;
  735.         UpdateDisplay();
  736.         SetSignButtons();
  737.     }
  738. }
  739.  
  740.  
  741. /****************************************************************/
  742. /*                                */
  743. /*   ROUTINE NAME:    SetSignButtons                */
  744. /*                                */
  745. /*   PURPOSE:    Enable/disable sign buttons            */
  746. /*                                */
  747. /****************************************************************/
  748. PRIVATE    void    SetSignButtons()
  749. {
  750.     if (isSigned) {
  751.         XtSetSensitive(usignW, True);
  752.         XtSetSensitive(signW, False);
  753.     } else {
  754.         XtSetSensitive(usignW, False);
  755.         XtSetSensitive(signW, True);
  756.     }
  757. }
  758.  
  759.  
  760. /****************************************************************/
  761. /*                                */
  762. /*   ROUTINE NAME:    Digit                    */
  763. /*                                */
  764. /*   PURPOSE:    Process a digit key.                */
  765. /*                                */
  766. /****************************************************************/
  767. /* ARGSUSED */
  768. PRIVATE    void    Digit(w, data)
  769. Widget        w;
  770. caddr_t        data;
  771. {
  772.     int    digit = (int) data;
  773.     int    oldAc;
  774.     
  775.     if (digit >= radix) {
  776.         Beep();
  777.     } else {
  778.         if (newNumber) {
  779.             ac = 0;
  780.             newNumber = False;
  781.             acPushed = False;
  782.         }
  783.         oldAc = ac;
  784.         ac *= radix;
  785.         ac += digit;
  786.         if  (((radix == 10) && isSigned) ? (oldAc <= ac) : ( (unsigned) oldAc <= (unsigned) ac)) {
  787.             UpdateDisplay();
  788.         } else {
  789.             ac = oldAc;
  790.             Beep();
  791.         }
  792.     }
  793. }
  794.  
  795.  
  796. /****************************************************************/
  797. /*                                */
  798. /*   ROUTINE NAME:    Clear                    */
  799. /*                                */
  800. /*   PURPOSE:    Clear the accumulator                */
  801. /*                                */
  802. /****************************************************************/
  803. PRIVATE    void    Clear()
  804. {
  805.     if (ac) {
  806.         ac = 0;
  807.         UpdateDisplay();
  808.     }
  809.     acPushed = False;
  810. }
  811.  
  812. /****************************************************************/
  813. /*                                */
  814. /*   ROUTINE NAME:    AllClear                */
  815. /*                                */
  816. /*   PURPOSE:    Reset the calculator                */
  817. /*                                */
  818. /****************************************************************/
  819. PRIVATE    void    AllClear()
  820. {
  821.     ac = 0;
  822.     radix = 10;
  823.     memory = 0;
  824.     isSigned = True;
  825.     bitsWide = 32;
  826.     emptyArgs();
  827.     emptyOps();
  828.     PushOp('$');
  829.     newNumber = True;
  830.     acPushed = False;
  831.         
  832.     SetRadixButtons();
  833.     SetSizeButtons();
  834.     SetSignButtons();
  835.     UpdateDisplay();
  836. }
  837.  
  838.  
  839. /****************************************************************/
  840. /*                                */
  841. /*   ROUTINE NAME: MakeButtons                    */
  842. /*                                */
  843. /*   PURPOSE: Make a form & all the buttons            */
  844. /*                                */
  845. /****************************************************************/
  846. PRIVATE    Widget    MakeButtons(parent)
  847. Widget        parent;
  848. {
  849.     int        argCount;
  850.     Arg        args[10];
  851.     Widget        buttonForm;
  852.     Widget        button = NULL;
  853.     Widget        vertButton = NULL;
  854.     int        i;
  855.     Dimension    width;
  856.     Dimension    maxWidth = 0;
  857.  
  858.     /************************************************/
  859.     /* make a label to hold the display        */
  860.     /************************************************/
  861.     resetArgs();
  862.     buttonForm = createManagedWidget("buttonForm", formWidgetClass, parent);
  863.     XtAugmentTranslations(buttonForm, translations);
  864.     
  865.     /************************************************/
  866.     /* Make each of the buttons            */
  867.     /************************************************/
  868.     for (i = 0; i < XtNumber(buttonList); i++) {
  869.         resetArgs();
  870.         setArg(XtNcallback, &buttonList[i].callback[0]);
  871.         setArg(XtNfromHoriz, button);
  872.         setArg(XtNfromVert, vertButton);
  873.         setArg(XtNlabel,    buttonList[i].name);
  874.         if (buttonList[i].name[0] == '\0') {
  875.             setArg(XtNmappedWhenManaged, False);
  876.         }
  877.         button = createManagedWidget(buttonList[i].type, commandWidgetClass, buttonForm);
  878.         buttonList[i].w = button;
  879.         if (buttonList[i].wPtr) *buttonList[i].wPtr = button;
  880.                 
  881.         XtAugmentTranslations(button, translations);
  882.  
  883.         if (((i+1) % 5) == 0) {
  884.             vertButton = button;
  885.             button = NULL;
  886.         }
  887.         
  888.     }
  889.  
  890.     /************************************************/
  891.     /* Force all buttons to be the same width    */
  892.     /************************************************/
  893.     for (i = 0; i < XtNumber(buttonList); i++) {
  894.         resetArgs();
  895.         setArg(XtNwidth, &width);
  896.         XtGetValues(buttonList[i].w, args, argCount);
  897.         maxWidth = width > maxWidth ? width : maxWidth;
  898.     }
  899.  
  900.     for (i = 0; i < XtNumber(buttonList); i++) {        
  901.         resetArgs();
  902.         setArg(XtNwidth, maxWidth);
  903.         XtSetValues(buttonList[i].w, args, argCount);
  904.     }
  905.     
  906.     return (buttonForm);
  907.  
  908. }
  909.  
  910.  
  911.  
  912. /****************************************************************/
  913. /*                                */
  914. /*   ROUTINE NAME: MakeDisplay                    */
  915. /*                                */
  916. /*   PURPOSE: Make the calculator display            */
  917. /*                                */
  918. /****************************************************************/
  919. PRIVATE    Widget    MakeDisplay(parent)
  920. Widget        parent;
  921. {
  922.     int    argCount;
  923.     Arg    args[10];
  924.  
  925.     /************************************************/
  926.     /* make a label to hold the display        */
  927.     /************************************************/
  928.     resetArgs();
  929.     setArg(XtNjustify, XtJustifyRight);
  930.     setArg(XtNlabel, "-00000000000000000000000000000000");
  931.     display = XtCreateManagedWidget("display", labelWidgetClass, parent, args, argCount);
  932.  
  933.  
  934.     XtAugmentTranslations(display, translations);
  935.  
  936.     return (display);
  937. }
  938.  
  939.  
  940. /****************************************************************/
  941. /*                                */
  942. /*   ROUTINE NAME: MakeHexcalc                    */
  943. /*                                */
  944. /*   PURPOSE: Make the calculator                */
  945. /*                                */
  946. /****************************************************************/
  947. PRIVATE    void    MakeHexcalc(parent)
  948. Widget        parent;
  949. {
  950.     int    argCount;
  951.     Arg    args[10];
  952.     Widget    whole;    
  953.     
  954.     /************************************************/
  955.     /* Build a pane to hold the world        */
  956.     /************************************************/
  957.     resetArgs();
  958.     setArg(XtNgripIndent, -10);
  959.     whole = XtCreateManagedWidget("wholePane", panedWidgetClass, 
  960.         parent, args, argCount);
  961.     
  962.  
  963.     XtAugmentTranslations(whole, translations);
  964.     /************************************************/
  965.     /* Make the display and buttons            */
  966.     /************************************************/    
  967.     (void) MakeDisplay(whole);
  968.     (void) MakeButtons(whole);
  969. }
  970.  
  971.  
  972. /****************************************************************/
  973. /*                                */
  974. /*   ROUTINE NAME: main                        */
  975. /*                                */
  976. /*   PURPOSE: Process entry point.                */
  977. /*                                */
  978. /****************************************************************/
  979. int    main(argc, argv)
  980. int    argc;
  981. char    *argv[];
  982. {
  983.  
  984.     /************************************************/    
  985.     /* Build top level widget            */
  986.     /************************************************/
  987.     topLevel = XtInitialize("hexcalc", "Hexcalc", NULL, 0, &argc, argv);
  988.     XtAppAddActions(XtWidgetToApplicationContext(topLevel), actions, XtNumber(actions));
  989.     translations =     XtParseTranslationTable(defaultTranslations);
  990.  
  991.     /************************************************/
  992.     /* layout and initialize other widgets        */
  993.     /* Then process events.                */
  994.     /************************************************/
  995.  
  996.     MakeHexcalc(topLevel);
  997.     XtRealizeWidget(topLevel);
  998.     AllClear();
  999.     XtMainLoop();
  1000.  
  1001.     return (0);
  1002. }
  1003.  
  1004.  
  1005.